from datetime import datetime
from django.core.exceptions import ValidationError
import re

def validate_id_card(value):
    """
    验证身份证号的有效性
    """
    if not value:  # 允许为空
        return

    # 基本格式验证
    if not re.match(r'^\d{17}[\dXx]$', value):
        raise ValidationError('身份证号格式不正确')

    # 地区码验证（前6位）
    area_codes = {
        '11': '北京', '12': '天津', '13': '河北', '14': '山西', '15': '内蒙古',
        '21': '辽宁', '22': '吉林', '23': '黑龙江',
        '31': '上海', '32': '江苏', '33': '浙江', '34': '安徽', '35': '福建',
        '36': '江西', '37': '山东',
        '41': '河南', '42': '湖北', '43': '湖南', '44': '广东', '45': '广西',
        '46': '海南',
        '50': '重庆', '51': '四川', '52': '贵州', '53': '云南', '54': '西藏',
        '61': '陕西', '62': '甘肃', '63': '青海', '64': '宁夏', '65': '新疆',
        '71': '台湾',
        '81': '香港', '82': '澳门',
    }

    if value[:2] not in area_codes:
        raise ValidationError('身份证号地区码不正确')

    # 出生日期验证（第7-14位）
    try:
        birth_date = datetime.strptime(value[6:14], '%Y%m%d')
        today = datetime.now()
        if birth_date > today:
            raise ValidationError('出生日期不能大于当前日期')
        # 验证年龄是否在合理范围内（0-120岁）
        age = today.year - birth_date.year - ((today.month, today.day) < (birth_date.month, birth_date.day))
        if not 0 <= age <= 120:
            raise ValidationError('出生日期不在合理范围内')
    except ValueError:
        raise ValidationError('身份证号中的出生日期无效')

    # 校验码验证（最后一位）
    factors = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
    checksum_dict = {0: '1', 1: '0', 2: 'X', 3: '9', 4: '8', 5: '7', 6: '6', 7: '5', 8: '4', 9: '3', 10: '2'}

    # 计算校验码
    checksum = 0
    for i in range(17):
        checksum += int(value[i]) * factors[i]
    checksum = checksum % 11
    correct_check_digit = checksum_dict[checksum]

    if value[-1].upper() != correct_check_digit:
        raise ValidationError('身份证号校验码不正确')